#pragma once

#include <iostream>
#include <vector>
#include <queue>
#include <unistd.h>
#include "LockGuard.hpp"
#include "Thread.hpp"
#include "Functions.hpp"
#include "Log.hpp"
using namespace std;

#define Default_Thread_Num 3

// 单例模式-懒汉
// 构造私有化，拷贝赋值删除，自动析构
// 考虑多线程开始的时候实例化线程池的线程安全问题，加锁
// 静态的成员线程池指针，静态的锁（后面解释为什么是静态），内部类实现自动析构

// todo两个队列的多线程调用线程池场景

template <class T>
class Thread_Pool
{
private:
    Thread_Pool(size_t num = Default_Thread_Num) : _num(num), _cond(_lock.ret_mutex())
    {
        for (int i = 1; i <= num; ++i)
        {
            // routine函数需要拿到任务队列，传this指针
            _threads.push_back(new Thread(i, routine, (void *)this));
        }
    }
    Thread_Pool(const Thread_Pool<T> &) = delete;
    Thread_Pool<T> &operator=(const Thread_Pool<T> &) = delete;
    // void operator delete(void*);

public:
    static Thread_Pool<T> *Creat_Threadpool(int num = Default_Thread_Num)
    {
        // 保证第一次实例化的时候线程安全
        if (_tp_ptr == nullptr)
        {
            // LockGuard_static(&_lock_static);
            // pthread_mutex_lock(&_lock_static);
            LockGuard_static lock(&_lock_static);
            if (_tp_ptr == nullptr)
            {
                massagelog(NORMAL, "%s\n", "线程池创建成功");
                _tp_ptr = new Thread_Pool<T>(num);
            }
            // pthread_mutex_unlock(&_lock_static);
        }

        return _tp_ptr;
    }

    void run()
    {
        for (auto &t : _threads)
        {
            t->run();
        }
    }

    //     // 列程函数负责从任务队列获取任务去执行
    // static void* routine(void* args)
    // {
    //     // 这里的args是从Thread函数的creat里获取的，Thread_Data
    //     Thread_Data* td = (Thread_Data*)args;
    //     Thread_Pool<T>* tp = (Thread_Pool<T>*)td->args;
    //     while(true)
    //     {

    //         // 拿任务
    //         T task;
    //         {
    //             LockGuard lock(&(tp->_lock));
    //             // LockGuard (tp->ret_plock());
    //             // LockGuard lock(tp->ret_plock());
    //             std::cout << td->name << "申请到锁--------------" << std::endl;
    //             while(tp->_tasks.empty())
    //             {
    //                 std::cout << td->name << "条件等待，阻塞中！" << tp->_tasks.size() << std::endl;
    //                 tp->_cond.wait();
    //                 // tp->cond_wait();
    //                 std::cout << td->name << "我被唤醒了" << tp->_tasks.size() << std::endl;
    //             }
    //             task = tp->gettask();
    //             std::cout << td->name << "释放锁------------" << std::endl;
    //         }
    //         // 处理任务
    //         std::cout << td->name << "处理任务：" << task._x << name_v[task._type] << task._y << "=" << task() << std::endl;
    //     }
    // }

    // 列程函数负责从任务队列获取任务去执行
    static void *routine(void *args)
    {
        // 这里的args是从Thread函数的creat里获取的，Thread_Data
        Thread_Data *td = (Thread_Data *)args;
        Thread_Pool<T> *tp = (Thread_Pool<T> *)td->args;
        while (true)
        {

            // 拿任务
            T task;
            {
                // LockGuard lock(&(tp->_lock));
                // LockGuard (tp->ret_plock()); // 犯得最sb的错误
                LockGuard lock(tp->ret_plock());
                while (tp->Tasks_Is_Empty())
                {
                    massagelog(DEBUG, "%s %s %d\n", td->name.c_str(), "条件等待，阻塞中！", tp->ret_tasks_size());
                    // tp->_cond.wait();
                    tp->cond_wait();
                    massagelog(DEBUG, "%s %s %d\n", td->name.c_str(), "我被唤醒了", tp->ret_tasks_size());
                }
                task = tp->gettask();
            }
            // 处理任务
            massagelog(NORMAL, "%s %s %d %s %d %s %d\n", td->name.c_str(),
                       "处理任务：", task._x, name_v[task._type].c_str(), task._y, "=", task());
        }
    }

    // 生产者放任务
    void push_task(const T &task)
    {
        LockGuard lock(&_lock);
        _tasks.push(task);

        _cond.signal();
    }

    ~Thread_Pool()
    {
        for (auto &t : _threads)
        {
            t->join();
        }
        pthread_mutex_destroy(&_lock_static);
    }

    bool Tasks_Is_Empty()
    {
        return _tasks.empty();
    }

    Lock *ret_plock()
    {
        return &_lock;
    }

    int ret_tasks_size()
    {
        return _tasks.size();
    }

    void cond_wait()
    {
        _cond.wait();
    }

    T gettask()
    {
        T task = _tasks.front();
        _tasks.pop();
        return task;
    }

private:
    std::vector<Thread *> _threads;
    size_t _num;
    std::queue<T> _tasks;
    Lock _lock;
    Cond _cond;

    static Thread_Pool<T> *_tp_ptr;
    // static Lock _creat_lock;
    // static Lock_static _lock_static;
    static pthread_mutex_t _lock_static;
};

// static定义的是静态的，必须要用静态的初始化方式
// template<class T>
// Lock Thread_Pool<T>::_creat_lock;

template <class T>
Thread_Pool<T> *Thread_Pool<T>::_tp_ptr = nullptr;

// template<class T>
// Lock_static Thread_Pool<T>::_lock_static;
template <class T>
pthread_mutex_t Thread_Pool<T>::_lock_static = PTHREAD_MUTEX_INITIALIZER;

// 第二版

// #pragma once

// #include <iostream>
// #include <vector>
// #include <queue>
// #include <unistd.h>
// #include "LockGuard.hpp"
// #include "Thread.hpp"
// #include "Functions.hpp"

// #define Default_Thread_Num 3

// template <class T>
// class Thread_Pool
// {
// public:
//     Thread_Pool(size_t num = Default_Thread_Num) : _num(num)
//     {
//         for (int i = 1; i <= num; ++i)
//         {
//             pthread_mutex_init(&_lock, nullptr);
//             pthread_cond_init(&_cond, nullptr);
//             // routine函数需要拿到任务队列，传this指针
//             _threads.push_back(new Thread(i, routine, (void *)this));
//         }
//     }

//     void run()
//     {
//         for (auto &t : _threads)
//         {
//             t->run();
//         }
//     }

//     // 列程函数负责从任务队列获取任务去执行
//     static void *routine(void *args)
//     {
//         // 这里的args是从Thread函数的creat里获取的，Thread_Data
//         Thread_Data *td = (Thread_Data *)args;
//         Thread_Pool<T> *tp = (Thread_Pool<T> *)td->args;
//         while (true)
//         {
//             // 拿任务
//             T task;
//             {
//                 pthread_mutex_lock(tp->ret_mutex());
//                 std::cout << td->name << "申请到锁--------------" << std::endl;
//                 while (tp->_tasks.empty())
//                 {
//                     std::cout << td->name << "条件等待，阻塞中！" << tp->_tasks.size() << std::endl;
//                     pthread_cond_wait(&(tp->_cond), tp->ret_mutex());
//                     std::cout << td->name << "我被唤醒了" << tp->_tasks.size() << std::endl;
//                 }
//                 task = tp->_tasks.front();
//                 tp->_tasks.pop();
//                 std::cout << td->name << "释放锁------------" << std::endl;
//                 pthread_mutex_unlock(tp->ret_mutex());
//             }
//             // 处理任务
//             std::cout << td->name << "处理任务：" << task._x << name_v[task._type] << task._y << "=" << task() << std::endl;
//             usleep(1000);
//         }
//     }

//     // static void* routine(void* args)
//     // {
//     //     Thread_Data* td = (Thread_Data*)args;
//     //     Thread_Pool<T>* tp = (Thread_Pool<T>*)td->args;
//     //     while(true)
//     //     {
//     //         T task;
//     //         {
//     //             LockGuard lock(Lock);
//     //         }
//     //     }

//     // }

//     // 生产者放任务
//     void push_task(const T &task)
//     {
//         pthread_mutex_lock(&_lock);
//         _tasks.push(task);
//         pthread_cond_signal(&_cond);

//         std::cout << "唤醒n个~" << std::endl;
//         pthread_mutex_unlock(&_lock);
//     }

//     ~Thread_Pool()
//     {
//         for (auto &t : _threads)
//         {
//             t->join();
//         }
//     }

//     pthread_mutex_t* ret_mutex()
//     {
//         return &_lock;
//     }

//     bool Tasks_Is_Empty()
//     {
//         return _tasks.empty();
//     }

// public:
//     std::vector<Thread *> _threads;
//     size_t _num;
//     std::queue<T> _tasks;

//     pthread_cond_t _cond;
//     pthread_mutex_t _lock;
// };
